Merge pull request #71 from romoloman/master
[openXsensor.git] / Hott doc / Message.cpp
bloba589303b2b81ae55e4a2020c3dd53082bc04e54e
1 //
2 // LiPoMetre pour télémesure Graupner Hott
3 //
4 // Gestion messagerie Hott
5 //
6 // Auteur : www.thyzoon.fr
7 //
9 #include <EEPROM.h>
10 #include "Message.h"
11 #include "Tension_Lipo.h"
14 #define VERSION "0.60"
16 #define LEDPIN_OFF PORTB &= ~(1<<5);
17 #define LEDPIN_ON PORTB |= (1<<5);
18 // -------------------------------------
19 // Valeurs par défaut stockées en EEPROM
21 #define SEUIL_TENSION_ALARME 340 // 350 = 3.40V
22 #define SON_ALARME 9 // Bip
23 #define REPETITION_ALARME 15 // 15 s
25 #define ALARME_OFF 0
27 // buffer message
28 static uint8_t _hott_serial_buffer[173]; //création d'une variable tampon pour stocker les struct
30 // pointer des structures vers le tampon "_hott_serial_buffer"
31 struct HOTT_GAM_MSG *hott_gam_msg = (struct HOTT_GAM_MSG *)&_hott_serial_buffer[0];
32 struct HOTT_TEXTMODE_MSG *hott_txt_msg = (struct HOTT_TEXTMODE_MSG *)&_hott_serial_buffer[0];
34 word seuil_tension_alarme; // seuil tension alarme (1 element)
35 word son_alarme; // son alarme
36 word repetition; // Repetition alarme
38 // For communication
39 static uint8_t octet1 = 0; // reception
40 static uint8_t octet2 = 0; // reception
42 // Variables
43 static uint8_t nb_Lipo = 3; // Nb d'éléments accu Lipo
44 float Lipo_total = 0; // Tension totale mesurée
45 float Lipo_Total_Mini = 26; // Tension totale mini mesurée
46 float lipo1 = 0.0; // Tension sur chacun des éléments
47 float lipo2 = 0.0;
48 float lipo3 = 0.0;
49 float lipo4 = 0.0;
50 float lipo5 = 0.0;
51 float lipo6 = 0.0;
52 float lipo_mini = 0.0; // Valeur tension mini element
53 uint8_t Jauge = 0; // Jauge carburant
54 uint8_t Alarme = false; // Alarme tension basse
55 uint8_t Alarme_On = false; // Alarme en marche
57 unsigned long temps = 0; // Gestion du temps depuis mise sous tension en ms
58 unsigned long temps_alarme = 0; // date de l'alarme de tension basse
61 // Sauvegardedes parametres en EEPROM
63 !WARNING!
64 Writing takes 3.3ms.
65 Maximum life of the EEPROM is 100000 writings/readings.
67 // Adresses des parametres en EEPROM, tous les parametres sont stockes sur 16 bits.
68 #define adr_eprom_init 0 // For the test for 1st time init of the Arduino (First power on)
69 #define adr_eprom_seuil_tension_alarme 2 // Tension seuil alarme
70 #define adr_eprom_son_alarme 4 // Son alarme
71 #define adr_eprom_repetition 6 // Repetition
74 extern TensionLipo tension;
76 GMessage::GMessage(){
79 void GMessage::init(){
81 // Initialisation COM 19200 bauds pour recepteur HOTT GRxx
82 Serial.begin (SERIAL_COM_SPEED);
84 // ******************************************************
85 // Test for 1st time init of the Arduino (First power on)
86 int test = read_eprom(adr_eprom_init);
87 if (test != 120)
89 write_eprom(adr_eprom_init,120);
90 write_eprom(adr_eprom_seuil_tension_alarme,SEUIL_TENSION_ALARME); // Seuil par défaut
91 write_eprom(adr_eprom_son_alarme,SON_ALARME); // Son par défaut
92 write_eprom(adr_eprom_repetition,REPETITION_ALARME);
94 // Read saved values from EEPROM
95 seuil_tension_alarme = read_eprom(adr_eprom_seuil_tension_alarme); // sens gaz Normal / Inversé
96 son_alarme = read_eprom(adr_eprom_son_alarme); // son alarme
97 repetition = read_eprom(adr_eprom_repetition); //
99 // Init. pour certaines données
100 setLipo (0,1);
101 setLipo (0,2);
102 setLipo (0,3);
103 setLipo (0,4);
104 setLipo (0,5);
105 setLipo (0,6);
106 setAltitudeInMeters (0);
107 setClimbrate (0);
108 setClimbrate_M3 (0);
109 setTemp (0,2);
110 setVoltage2(0);
112 nb_Lipo = tension.Detect (); // detection du nombre d'elements 2S a 6S
113 setTemp (nb_Lipo,1); // affichage nb element a la place de Temp1
116 // Lecture d'un mot de 16 bits en EEPROM
117 uint16_t GMessage::read_eprom(int address){
118 return (uint16_t) EEPROM.read(address) * 256 + EEPROM.read(address+1) ;
121 // Ecriture d'un mot de 16 bits en EEPROM
122 void GMessage::write_eprom(int address,uint16_t val){
123 EEPROM.write(address, val / 256);
124 EEPROM.write(address+1,val % 256 );
127 // Initialisation message GAM (General Air Module)
128 void GMessage::init_gam_msg(){
129 //met tous à Zero, puis on modifie les constantes
130 memset(hott_gam_msg, 0, sizeof(struct HOTT_GAM_MSG));
131 hott_gam_msg->start_byte = 0x7c;
132 hott_gam_msg->gam_sensor_id = HOTT_TELEMETRY_GAM_SENSOR_ID;
133 hott_gam_msg->sensor_id = 0xd0;
134 hott_gam_msg->stop_byte = 0x7d;
137 // Emission de la trame
138 void GMessage::send(int lenght){
139 uint8_t sum = 0;
140 delay(5);
141 for(int i = 0; i < lenght-1; i++){
142 sum = sum + _hott_serial_buffer[i];
143 Serial.write (_hott_serial_buffer[i]);
144 delayMicroseconds(HOTTV4_TX_DELAY);
146 Serial.read(); // A cause du rebouclage TX <--> RX Lecture de l'octet émis
148 //Emision du checksum
149 Serial.write (sum);
150 delayMicroseconds(HOTTV4_TX_DELAY);
151 Serial.read(); // A cause du rebouclage TX <--> RX Lecture de l'octet émis
154 void GMessage::main(){
156 static byte page_settings = 1;//numéro de la page de settings à afficher
158 if (Serial.available() >= 2) {
159 uint8_t octet1 = Serial.read();
160 switch (octet1) {
161 case HOTT_BINARY_MODE_REQUEST_ID:
163 uint8_t octet2 = Serial.read();
164 // Demande RX Module = $80 $XX
165 switch (octet2) {
166 case HOTT_TELEMETRY_GAM_SENSOR_ID: //0x8D
168 // init structure
169 init_gam_msg();
171 // ******************************************************
172 LEDPIN_ON
174 // Mesure des tensions
175 lipo1 = tension.Tension_Lipo1();
176 lipo2 = tension.Tension_Lipo2();
177 lipo3 = tension.Tension_Lipo3();
178 lipo4 = tension.Tension_Lipo4();
179 lipo5 = tension.Tension_Lipo5();
180 lipo6 = tension.Tension_Lipo6();
182 // Calcul de la valeur de chaque elements
183 switch (nb_Lipo){
184 case 2 :
185 Lipo_total = lipo2;
186 lipo2 = lipo2 - lipo1;
187 break;
189 case 3 :
190 Lipo_total = lipo3;
191 lipo3 = lipo3 - lipo2;
192 lipo2 = lipo2 - lipo1;
193 setLipo (lipo3,3);
194 break;
196 case 4 :
197 Lipo_total = lipo4;
198 lipo4 = lipo4 - lipo3;
199 lipo3 = lipo3 - lipo2;
200 lipo2 = lipo2 - lipo1;
201 setLipo (lipo3,3);
202 setLipo (lipo4,4);
203 break;
205 case 5 :
206 Lipo_total = lipo5;
207 lipo5 = lipo5 - lipo4;
208 lipo4 = lipo4 - lipo3;
209 lipo3 = lipo3 - lipo2;
210 lipo2 = lipo2 - lipo1;
211 setLipo (lipo3,3);
212 setLipo (lipo4,4);
213 setLipo (lipo5,5);
214 break;
216 case 6 :
217 Lipo_total = lipo6;
218 lipo6 = lipo6 - lipo5;
219 lipo5 = lipo5 - lipo4;
220 lipo4 = lipo4 - lipo3;
221 lipo3 = lipo3 - lipo2;
222 lipo2 = lipo2 - lipo1;
223 setLipo (lipo3,3);
224 setLipo (lipo4,4);
225 setLipo (lipo5,5);
226 setLipo (lipo6,6);
227 break;
229 default : ;
232 // par défaut 1 et 2
233 setLipo (lipo1,1);
234 setLipo (lipo2,2);
236 setVoltage1(Lipo_total); // Affichage sur Batt 1
237 setMainVoltage(Lipo_total); // Affichage sur principal
239 if (Lipo_total < Lipo_Total_Mini) {
240 Lipo_Total_Mini = Lipo_total; // mémorise la valeur mini
241 setVoltage2(Lipo_Total_Mini);
245 // Recherche element le plus faible
246 // pour affichage jauge
247 // et gestion alarme radio
248 lipo_mini = tension.Lipo_Mini(nb_Lipo,lipo1,lipo2,lipo3,lipo4,lipo5,lipo6);
250 if ((lipo_mini >= 3.6)&&(lipo_mini <= 4.2))
251 Jauge = 100 - (4.2 - lipo_mini) / 0.0066667;
252 else if ((lipo_mini < 3.6) && (lipo_mini >= 3.0))
253 Jauge = (lipo_mini - 3.0) / 0.06 ;
254 else if (lipo_mini < 3.0)
255 Jauge = 0;
257 // Alarme
258 if (lipo_mini < (float(seuil_tension_alarme)/100.0))
259 Alarme = true;
260 else
261 Alarme = false;
263 if (Alarme_On == true) {
264 alarme (son_alarme); // Bip alarme
265 temps_alarme = millis (); // temps courant
266 Alarme_On = false; // Flag faux
268 else {
269 alarme (ALARME_OFF);} // fin d'alarme
271 // Affichage jauge carburant
272 setFuelPercent (Jauge);
274 LEDPIN_OFF
276 if (Alarme == true) {
277 temps = millis ();
278 if (temps > temps_alarme + (repetition * 1000)) { // repetition entre alarmes
279 Alarme_On = true;
283 send(sizeof(struct HOTT_GAM_MSG));
284 break;
285 } //end case GAM*/
286 } //end case octet 2
287 break;
290 case HOTT_TEXT_MODE_REQUEST_ID:
292 uint8_t octet3 = Serial.read();
293 byte id_sensor = (octet3 >> 4);
294 byte id_key = octet3 & 0x0f;
295 static byte ligne_select = 1 ; // Ligne 1 selectionnée par défaut
296 static int8_t ligne_edit = -1 ;
297 hott_txt_msg->start_byte = 0x7b;
298 hott_txt_msg->esc = 0;
299 hott_txt_msg->warning_beeps = 0;
301 memset((char *)&hott_txt_msg->text, 0x20, HOTT_TEXTMODE_MSG_TEXT_LEN);
302 hott_txt_msg->stop_byte = 0x7d;
304 if (id_sensor == (HOTT_TELEMETRY_GAM_SENSOR_ID & 0x0f))
307 switch (page_settings) { // Pages de parametres LiPoMetre
309 case 1: //PAGE 1
311 if (ligne_edit == -1)
313 switch (id_key) {
314 case HOTT_KEY_UP :
315 ligne_select = min(3,ligne_select + 1); // Ligne 2 maxi
316 break;
318 case HOTT_KEY_DOWN :
319 ligne_select = max(1,ligne_select - 1); //Ligne 1 mini
320 break;
322 case HOTT_KEY_SET : // Sélection de la ligne courante
323 ligne_edit = ligne_select ;
324 break;
326 case HOTT_KEY_LEFT : // Sortie
327 hott_txt_msg->esc = 0x01;
328 ligne_edit = -1 ;
329 ligne_select = 1;
330 break;
332 case HOTT_KEY_RIGHT :
333 page_settings = 1;
334 ligne_edit = -1 ;
335 ligne_select = 1;
336 break;
338 default : break;
342 //*************************************************
343 //LIGNE 2 SELECTIONNEE = Seuil alarme
344 else if (ligne_select == 1)
346 switch (id_key) {
347 case HOTT_KEY_UP :
348 seuil_tension_alarme = seuil_tension_alarme +5;
349 if (seuil_tension_alarme >380)
350 seuil_tension_alarme = 380;
351 break;
353 case HOTT_KEY_DOWN :
354 seuil_tension_alarme = seuil_tension_alarme -5;
355 if (seuil_tension_alarme <300)
356 seuil_tension_alarme = 300;
357 break;
359 case HOTT_KEY_SET :
360 ligne_edit = -1 ;
361 write_eprom(adr_eprom_seuil_tension_alarme,seuil_tension_alarme); // Ecriture en memoire
362 break;
364 default : break;
368 //*************************************************
369 //LIGNE 3 SELECTIONNEE = Son alarme
370 else if (ligne_select == 2)
372 switch (id_key) {
373 case HOTT_KEY_UP :
374 son_alarme = son_alarme + 1;
375 if (son_alarme > 26)
376 son_alarme = 26;
377 break;
379 case HOTT_KEY_DOWN :
380 son_alarme = son_alarme - 1;
381 if (son_alarme < 1)
382 son_alarme = 1;
383 break;
385 case HOTT_KEY_SET :
386 ligne_edit = -1 ;
387 write_eprom(adr_eprom_son_alarme,son_alarme); // Ecriture en memoire
388 break;
390 default : break;
394 //*************************************************
395 //LIGNE 4 SELECTIONNEE = Repetition alarme
396 else if (ligne_select == 3)
398 switch (id_key) {
399 case HOTT_KEY_UP :
400 repetition = repetition + 5;
401 if (repetition > 30)
402 repetition = 30;
403 break;
405 case HOTT_KEY_DOWN :
406 repetition = repetition - 5;
407 if (repetition < 10)
408 repetition = 10;
409 break;
411 case HOTT_KEY_SET :
412 ligne_edit = -1 ;
413 write_eprom(adr_eprom_repetition,repetition); // Ecriture en memoire
414 break;
416 default : break;
421 //******************************************************************************************
422 // Affichage de la page 1
423 //ligne 0:
424 snprintf((char *)&hott_txt_msg->text[0],21," * LiPoMetre V%s *",VERSION);
425 //ligne 1:
426 snprintf((char *)&hott_txt_msg->text[1],21," Seuil alarme %i.%iV",int(seuil_tension_alarme/100),int(seuil_tension_alarme%100)) ; //float(seuil_tension_alarme)/100.0);
427 //ligne 2:
428 snprintf((char *)&hott_txt_msg->text[2],21," Son alarme %2i",son_alarme);
429 //ligne 3:
430 snprintf((char *)&hott_txt_msg->text[3],21," Repet. alarme %2is",repetition);
431 //ligne 4:
432 snprintf((char *)&hott_txt_msg->text[4],21," ------------------- ");
433 //ligne 5:
434 snprintf((char *)&hott_txt_msg->text[5],21," LIPO %iS", nb_Lipo);
435 //ligne 6:
436 snprintf((char *)&hott_txt_msg->text[6],21," ------------------- ");
437 //ligne 7:
438 snprintf((char *)&hott_txt_msg->text[7],21," thyzoon.fr 2015");
440 hott_txt_msg->text[ligne_select][0] = '>';
441 _hott_invert_ligne(ligne_edit);
442 break;
443 }//END PAGE 1
445 default://PAGE
447 break;
450 }//END SETTINGS
452 } // END IF
454 //********************************************************************************************************************
456 else if(id_sensor == (HOTT_TELEMETRY_GEA_SENSOR_ID & 0x0f)) {
457 snprintf((char *)&hott_txt_msg->text[0],21,"Module EAM");
458 snprintf((char *)&hott_txt_msg->text[1],21,"----------");
459 snprintf((char *)&hott_txt_msg->text[2],21,"Selectionner :");
460 snprintf((char *)&hott_txt_msg->text[3],21," GENERAL");
462 else if(id_sensor == (HOTT_TELEMETRY_VARIO_SENSOR_ID & 0x0f)) {
463 snprintf((char *)&hott_txt_msg->text[0],21,"Module VARIO");
464 snprintf((char *)&hott_txt_msg->text[1],21,"------------");
465 snprintf((char *)&hott_txt_msg->text[2],21,"Selectionner :");
466 snprintf((char *)&hott_txt_msg->text[3],21," GENERAL");
468 else {
469 snprintf((char *)&hott_txt_msg->text[0],21,"Module inconnu");
470 snprintf((char *)&hott_txt_msg->text[1],21,"--------------");
471 snprintf((char *)&hott_txt_msg->text[2],21,"Selectionner :");
472 snprintf((char *)&hott_txt_msg->text[3],21," GENERAL");
475 // Emission en mode texte
476 _hott_send_text_msg();
477 break;
483 //////////////////////////////////////////////////
484 // Tension principale (resolution 0.1V)
485 void GMessage::setMainVoltage(float tension){
486 hott_gam_msg->main_voltage = (uint16_t) (tension * 10);
489 // Batterie 1 (resolution 0.1V)
490 void GMessage::setVoltage1(float volt){
491 hott_gam_msg->Battery1 = (uint16_t) (volt * 10);
494 // Batterie 2 (resolution 0.1V)
495 void GMessage::setVoltage2(float volt){
496 hott_gam_msg->Battery2 = (uint16_t) (volt * 10);
499 // Element Lipo n (resolution 0.02V)
500 void GMessage::setLipo(float volt, int lipo){
502 if (lipo >= 1 and lipo <= 6)
504 lipo--;
505 hott_gam_msg->cell[lipo] = (uint16_t) 100 * volt / 2 ;
507 if (volt/2 <= hott_gam_msg->min_cell_volt || hott_gam_msg->min_cell_volt ==0)
509 hott_gam_msg->min_cell_volt = (uint16_t) 100 * volt/2 ;
510 hott_gam_msg->min_cell_volt_num = lipo;
515 // Altitude relative en metres : -500 / +9999 [m]
516 void GMessage::setAltitudeInMeters(uint16_t alti){
517 hott_gam_msg->altitude = alti + 500;
520 // Temperature : -20 a +235° C
522 void GMessage::setTemp(int temp, int capteur){
523 if(temp < -20)
524 temp = -20;
525 else if(temp > 234)
526 temp = 235;
527 if (capteur < 1)
528 capteur = 1;
529 if (capteur > 2)
530 capteur = 2;
531 if (capteur == 1)
532 hott_gam_msg->temperature1 = temp + 20;
533 else if (capteur == 2)
534 hott_gam_msg->temperature2 = temp + 20;
537 // Niveau reservoir : 0%, 25%, 50%, 75%, 100%
539 void GMessage::setFuelPercent(uint8_t pourcent){
540 if(pourcent > 100)
541 pourcent = 100;
542 else if(pourcent < 0)
543 pourcent = 0;
544 hott_gam_msg->fuel_procent = pourcent ;
547 // niveau reservoir en ml : 0 a 65535 ml
549 void GMessage::setFuelMilliliters(uint16_t ml){
550 hott_gam_msg->fuel_ml = ml ;
553 // Rotation : 0 a 655350 tr/min
556 void GMessage::setRPM(uint16_t rpm){
557 hott_gam_msg->rpm = rpm ;
560 // Set climbrates
561 void GMessage::setClimbrate(uint16_t climb_L){
562 hott_gam_msg->climbrate_L = climb_L+30000;
565 void GMessage::setClimbrate_M3(int climb3s){
566 hott_gam_msg->climbrate3s = climb3s+120;
569 // Set speed
570 void GMessage::setSpeed(float speed){
571 hott_gam_msg->climbrate3s = (int) speed;
576 // Alarme sonore sur radio
578 void GMessage::alarme (uint8_t son){
579 hott_gam_msg->warning_beeps = son;
582 void GMessage::_hott_send_text_msg() {
583 for(byte *_hott_msg_ptr = hott_txt_msg->text[0]; _hott_msg_ptr < &hott_txt_msg->stop_byte ; _hott_msg_ptr++){
584 if (*_hott_msg_ptr == 0)
585 *_hott_msg_ptr = 0x20;
587 //_hott_send_msg(_hott_serial_buffer, sizeof(struct HOTT_TEXTMODE_MSG));
588 send(sizeof(struct HOTT_TEXTMODE_MSG));
591 char * GMessage::_hott_invert_all_chars(char *str) {
592 return _hott_invert_chars(str, 0);
595 char * GMessage::_hott_invert_chars(char *str, int cnt) {
596 if(str == 0) return str;
597 int len = strlen(str);
598 if((len < cnt) && cnt > 0) len = cnt;
599 for(int i=0; i< len; i++) {
600 str[i] = (byte)(0x80 + (byte)str[i]);
602 return str;
605 void GMessage::_hott_invert_ligne(int ligne) {
606 if (ligne>= 0 && ligne<= 7)
607 for(int i=0; i< 21; i++) {
608 if (hott_txt_msg->text[ligne][i] == 0) //inversion du caratère null (fin de string)
609 hott_txt_msg->text[ligne][i] = (byte)(0x80 + 0x20);
610 else
611 hott_txt_msg->text[ligne][i] = (byte)(0x80 + (byte)hott_txt_msg->text[ligne][i]);